package ext.mango.aa.po;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import mango.functions.FuncDate;
import mango.functions.FuncString;
import mango.orm.DaoFactory;
import mango.orm.DBSession;
import mango.orm.DBSessionFactory;
import mango.orm.entity.Entity;
import mango.web.Info;
import ext.mango.aa.eo.EOAAUser;
import ext.mango.aa.eo.EOAAUserBak;
import ext.mango.aa.eo.EOAAUserToUserGroup;
import ext.mango.base.Const;
import ext.mango.base.Messages;
import ext.mango.base.POBase;

public class UserManager extends POBase{
    private final static Object LOCK_CREATE_USER = new Object();
    private final static Object LOCK_DELETE_USER = new Object();
    
    public boolean readusergroup(){
        // for oracle
//        String sql = "select usergroupid, usergroupid||'-'||usergroupname usergroupname from AAUserGroup";
        
        // for mysql
        String sql = "select usergroupid, concat(usergroupid, '-', usergroupname) usergroupname from AAUserGroup"; //$NON-NLS-1$
        if (!this.isSuperUser()){
            sql += " where usergroupid != 'Super'"; //$NON-NLS-1$
        }
        this.setResult(Entity.toJSON(DaoFactory.c(sql).listQuery(), "usergroup")); //$NON-NLS-1$
        return true;
    }
    
    public boolean updateuser(){
        synchronized (LOCK_CREATE_USER) {
            String oldId = this.getRequestParameter("QUERYID"); //$NON-NLS-1$
            String id = this.getRequestParameter("ID"); //$NON-NLS-1$
            String userName = this.getRequestParameter("USERNAME"); //$NON-NLS-1$
            String pwd = this.getRequestParameter("PWD"); //$NON-NLS-1$
            String userGroups = this.getRequestParameter("USERGROUPIDS"); //$NON-NLS-1$
            String aviliable = this.getRequestParameter("AVILIABLE"); //$NON-NLS-1$
            boolean avil = Boolean.parseBoolean(aviliable);
            //new user
            String[] ugs = userGroups.split(","); //$NON-NLS-1$
            if(FuncString.isBlank(oldId)) {
                EOAAUser user = new EOAAUser();
                user.setId(id).setPwd(pwd).setRegiestDate(new Date()).setUsrName(userName)
                .setAviliable(avil?"1":"0").setOperator(this.getCurrentUser().getId())
                .setLanguage(Const.LANG_CN); //$NON-NLS-1$ //$NON-NLS-2$
                Entity e = user.unique();
                if (e != null) {
                    this.addInfo(Info.ERROR, Messages.getString(this.getLanguage(),"useridisexists")); //$NON-NLS-1$
                    return false;
                }
                List<EOAAUserToUserGroup> tugs = new ArrayList<EOAAUserToUserGroup>();
                for (String ug : ugs) {
                    EOAAUserToUserGroup tug = new EOAAUserToUserGroup().setUserId(id).setUserGroupId(ug.trim());
                    tugs.add(tug);
                }
                DBSession session = DBSessionFactory.getSession();
                session.save(user);
                session.save(tugs);
                session.commit();
                this.addInfo(Info.SUCCESS, user.getId());
            }
            else {
                if(!this.isSuperUser() && this.isSuperUser(id)) {
                    this.addInfo(Info.ERROR, Messages.getString(this.getLanguage(),"superusercantbechange")); //$NON-NLS-1$
                }
                EOAAUser user = new EOAAUser();
                user.setId(id).setPwd(pwd).setUsrName(userName)
                    .setAviliable(avil?"1":"0").setOperator(this.getCurrentUser().getId())
                    .setModifyDate(new Date()).setModifyTime(FuncDate.getCurrentTime());
                EOAAUser u = (EOAAUser) user.unique();
                user.setRegiestDate(u.getRegiestDate()).setLanguage(u.getLanguage());
                EOAAUserBak userBak = new EOAAUserBak();
                userBak.setEntity(user.unique());
                userBak.setBakid(UUID.randomUUID().toString()).setBakType("updateuser").setModifyDate(new Date()).setModifyTime(FuncDate.getCurrentTime()); //$NON-NLS-1$
                List<EOAAUserToUserGroup> tugs = new ArrayList<EOAAUserToUserGroup>();
                for (String ug : ugs) {
                    EOAAUserToUserGroup tug = new EOAAUserToUserGroup().setUserId(id).setUserGroupId(ug.trim());
                    tugs.add(tug);
                }
                String delSql = "delete from AAUserToUserGroup where userid=?"; //$NON-NLS-1$
                DBSession session = DBSessionFactory.getSession();
                session.update(user);
                session.update(delSql, id);
                session.save(tugs);
                session.save(userBak);
                session.commit();
            }
        }
        return true;
    }
    
    public boolean readuser(){
        String userId = this.getRequestParameter("USERID"); //$NON-NLS-1$
        String groupId = this.getRequestParameter("GROUPID"); //$NON-NLS-1$
        
        String sql = "select id QUERYID, id, usrname username, pwd, FUNC_AA_GETUSERGROUPS(id) USERGROUPIDS, aviliable from AAUser a where 1=1 "; //$NON-NLS-1$
        if (!this.isSuperUser()) {
            sql += " and not exists(select 1 from AAUserToUserGroup where userid=a.id and usergroupid = 'Super')"; //$NON-NLS-1$
        }
        if (!FuncString.isBlank(userId)) {
            sql += " and (id like @userid or usrname like @name) "; //$NON-NLS-1$
        }
        if (!FuncString.isBlank(groupId)) {
            sql += " and exists(select 1 from AAUserToUserGroup where userid=a.id and usergroupid=@groupid) "; //$NON-NLS-1$
        }
        List<Entity> ret = DaoFactory.c(sql).setParamByName("userid", "%"+userId+"%").setParamByName("name", "%" + userId + "%").setParamByName("groupid", groupId).listQuery(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
        this.setResult(Entity.toJSON(ret, "user")); //$NON-NLS-1$
        return true;
    }
    
    public boolean readCurrentUserId(){
        this.addInfo(Info.SUCCESS, this.getCurrentUser().getId());
        return true;
    }
    
    public boolean deleteUser(){
        String id = this.getRequestParameter("ID"); //$NON-NLS-1$
        if(this.getCurrentUser().getId().equals(id)){
            this.addInfo(Info.ERROR, Messages.getString(this.getLanguage(),"cantdeleteself")); //$NON-NLS-1$
            return false;
        }
        if(!this.isSuperUser() && this.isSuperUser(id)){
            this.addInfo(Info.ERROR, Messages.getString(this.getLanguage(),"superusercantbedelete")); //$NON-NLS-1$
            return false;
        }
        synchronized (LOCK_DELETE_USER) {
            EOAAUser user = new EOAAUser().setId(id);
            EOAAUserBak bak = new EOAAUserBak();
            bak.setEntity(user.unique());
            bak.setModifyDate(new Date()).setModifyTime(FuncDate.getCurrentTime()).setBakid(UUID.randomUUID().toString()).setBakType("deleteuser"); //$NON-NLS-1$
            String sql = "delete from AAUserToUserGroup where userId=?"; //$NON-NLS-1$
            DBSession session = DBSessionFactory.getSession();
            session.delete(user);
            session.save(bak);
            session.execute(sql, id);
            session.commit();
            this.addInfo(Info.SUCCESS, "OK"); //$NON-NLS-1$
        }
        return true;
    }
    
    public boolean changePassword(){
        if(this.getCurrentUser() == null) {
            this.addInfo(Info.ERROR, Messages.getString(this.getLanguage(),"sessiontimeout")); //$NON-NLS-1$
            return false;
        }
        String pwd = this.getRequestParameter("pwd"); //$NON-NLS-1$
        String newpwd = this.getRequestParameter("newpwd"); //$NON-NLS-1$
        String confirmPwd = this.getRequestParameter("confirmpwd"); //$NON-NLS-1$
        
        if (!this.getCurrentUser().getPwd().equals(pwd)) {
            this.addInfo(Info.ERROR, Messages.getString(this.getLanguage(),"curpwderror")); //$NON-NLS-1$
            return false;
        }
        
        if(!newpwd.equals(confirmPwd)){
            this.addInfo(Info.ERROR, Messages.getString(this.getLanguage(),"pwddiff")); //$NON-NLS-1$
            return false;
        }
        
        if(pwd.equals(newpwd)) {
            this.addInfo(Info.ERROR, Messages.getString(this.getLanguage(),"pwdsame")); //$NON-NLS-1$
            return false;
        }
        EOAAUser user = new EOAAUser();
        user.setEntity(this.getCurrentUser());
        EOAAUserBak bak = new EOAAUserBak();
        bak.setEntity(user);
        bak.setBakid(UUID.randomUUID().toString()).setModifyDate(new Date()).setModifyTime(FuncDate.getCurrentTime()).setOperator(this.getCurrentUser().getId()).setBakType("changepassword"); //$NON-NLS-1$
        user.setPwd(newpwd).setModifyDate(new Date()).setModifyTime(FuncDate.getCurrentTime());
        DBSession session = DBSessionFactory.getSession();
        session.update(user);
        session.save(bak);
        session.commit();
        this.getCurrentUser().setPwd(newpwd);
        this.addInfo(Info.ERROR, Messages.getString(this.getLanguage(),"pwdchangesuccess")); //$NON-NLS-1$
        return true;
    }
    
    public boolean readLoginUser(){
        String user = this.getRequestParameter("USER"); //$NON-NLS-1$
        String startDate = this.getRequestParameter("STARTDATE"); //$NON-NLS-1$
        String endDate = this.getRequestParameter("ENDDATE"); //$NON-NLS-1$
        String status = this.getRequestParameter("STATUS"); //$NON-NLS-1$
//        String sql = "select id, USRID, USERNAME, logindate||' '||logintime logintime, logoutdate||' '||logouttime logouttime, remothost,sessionid,decode(status,'1','在线','不在线') status from AALoginHistory where 1=1 ";
        String sql = "select id, USRID, USERNAME, concat(logindate,' ',logintime) logintime, concat(logoutdate, ' ', logouttime) logouttime, remothost,sessionid, (select case when status='1' then '在线' else '不在线' end) status from AALoginHistory where 1=1 "; //$NON-NLS-1$
        if(!FuncString.isBlank(user)){
            sql += " and (usrid=@usrid or username like @username)"; //$NON-NLS-1$
        }
        if(!FuncString.isBlank(startDate)){
            sql += " and logindate>=@startdate"; //$NON-NLS-1$
        }
        if(!FuncString.isBlank(endDate)){
            sql += " and logindate<=@enddate"; //$NON-NLS-1$
        }
        if(!FuncString.isBlank(status)){
            sql += " and status=@status"; //$NON-NLS-1$
        }
//        sql += " order by logindate||logintime desc";
        sql += " order by concat(logindate, logintime) desc"; //$NON-NLS-1$
        List<Entity> ret = DaoFactory.c(sql).setParamByName("usrid", user) //$NON-NLS-1$
                 .setParamByName("username", user) //$NON-NLS-1$
                 .setParamByName("startdate", startDate) //$NON-NLS-1$
                 .setParamByName("enddate", endDate) //$NON-NLS-1$
                 .setParamByName("status", status).listQuery(); //$NON-NLS-1$
        this.setResult(Entity.toJSON(ret, "user")); //$NON-NLS-1$
        return true;
    }
    
    public boolean deletehistory(){
        String id = this.getRequestParameter("ID"); //$NON-NLS-1$
        String query = "select status from AALoginHistory where id=?"; //$NON-NLS-1$
        int status = DaoFactory.c(query).setParameter(id).getIntValue();
        if(status == 1){
            this.addInfo(Info.ERROR, Messages.getString(this.getLanguage(),"userwasonline")); //$NON-NLS-1$
            return false;
        }
        String sql = "delete from AALoginHistory where id=?"; //$NON-NLS-1$
        DaoFactory.c(sql).setParameter(id).execute();
        this.addInfo(Info.SUCCESS, "OK"); //$NON-NLS-1$
        return true;
    }
}
